﻿using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Net;
using System.Net.Sockets;
using System.Security.Cryptography;
using System.Threading;
using System.Threading.Tasks;

namespace Dot.NET47测试性能
{
    class Program
    {
        static void Main(string[] args)
        {
            //while (true)
            //{
            //    var q = new Queue<int>();
            //    var sw = Stopwatch.StartNew();
            //    for (int i = 0; i < 100_000_000; i++)
            //    {
            //        q.Enqueue(i);
            //        q.Dequeue();
            //    }
            //    Console.WriteLine(sw.Elapsed);
            //}

            //while (true)
            //{
            //    var l = new List<int>();
            //    var sw = Stopwatch.StartNew();
            //    for (int i = 0; i < 100_000_000; i++)
            //    {
            //        l.Add(i);
            //        l.RemoveAt(0);
            //    }
            //    Console.WriteLine(sw.Elapsed);
            //}

            //while (true)
            //{
            //    var q = new ConcurrentQueue<int>();
            //    var sw = Stopwatch.StartNew();

            //    for (int i = 0; i < 100_000_000; i++)
            //    {
            //        q.Enqueue(i);
            //        q.TryDequeue(out int _);
            //    }
            //    Console.WriteLine(sw.Elapsed);
            //}


            //while (true)
            //{
            //    const int Items = 100_000_000;
            //    var q = new ConcurrentQueue<int>();
            //    var sw = Stopwatch.StartNew();

            //    Task consumer = Task.Run(() =>
            //    {
            //        int total = 0;
            //        while (total < Items) if (q.TryDequeue(out int _)) total++;
            //    });
            //    for (int i = 0; i < Items; i++) q.Enqueue(i);
            //    consumer.Wait();

            //    Console.WriteLine(sw.Elapsed);
            //}

            //GC集合的数量

            //while (true)
            //{
            //    var q = new ConcurrentQueue<int>();
            //    int gen0 = GC.CollectionCount(0), gen1 = GC.CollectionCount(1), gen2 = GC.CollectionCount(2);
            //    for (int i = 0; i < 100_000_000; i++)
            //    {
            //        q.Enqueue(i);
            //        q.TryDequeue(out int _);
            //    }
            //    Console.WriteLine($"Gen0={GC.CollectionCount(0) - gen0} Gen1={GC.CollectionCount(1) - gen1} Gen2={GC.CollectionCount(2) - gen2}");
            //}

            //IEnumerable<int> zeroToTen = Enumerable.Range(0, 10);
            //IEnumerable<int> result = zeroToTen;
            //for (int i = 0; i < 10_000; i++)
            //{
            //    result = result.Concat(zeroToTen);
            //}

            //var sw = Stopwatch.StartNew();
            //foreach (int i in result) { }
            //Console.WriteLine(sw.Elapsed);

            //Console.ReadLine();


            //IEnumerable<int> tenMillionToZero = Enumerable.Range(0, 10_000_000).Reverse();

            //while (true)
            //{
            //    var sw = Stopwatch.StartNew();
            //    int fifth = tenMillionToZero.OrderBy(x => x).Skip(4).First();
            //    Console.WriteLine(sw.Elapsed);
            //}



            //byte[] raw = new byte[100 * 1024 * 1024];
            //for (int i = 0; i < raw.Length; i++) raw[i] = (byte)i;

            //using (var sha = SHA256.Create())
            //{
            //    var sw = Stopwatch.StartNew();
            //    sha.ComputeHash(raw);
            //    Console.WriteLine(sw.Elapsed);
            //}

            //网络
            //using (Socket listener = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp))
            //using (Socket client = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp))
            //{
            //    listener.Bind(new IPEndPoint(IPAddress.Loopback, 0));
            //    listener.Listen(1);

            //    Task connectTask = Task.Run(() => client.Connect(listener.LocalEndPoint));
            //    using (Socket server = listener.Accept())
            //    {
            //        connectTask.Wait();

            //        using (var clientAre = new AutoResetEvent(false))
            //        using (var clientSaea = new SocketAsyncEventArgs())
            //        using (var serverAre = new AutoResetEvent(false))
            //        using (var serverSaea = new SocketAsyncEventArgs())
            //        {
            //            byte[] sendBuffer = new byte[1000];
            //            clientSaea.SetBuffer(sendBuffer, 0, sendBuffer.Length);
            //            clientSaea.Completed += delegate { clientAre.Set(); };

            //            byte[] receiveBuffer = new byte[1000];
            //            serverSaea.SetBuffer(receiveBuffer, 0, receiveBuffer.Length);
            //            serverSaea.Completed += delegate { serverAre.Set(); };

            //            var sw = new Stopwatch();
            //            int gen0 = GC.CollectionCount(0), gen1 = GC.CollectionCount(1), gen2 = GC.CollectionCount(2);
            //            sw.Start();

            //            for (int i = 0; i < 1_000_000; i++)
            //            {
            //                if (client.SendAsync(clientSaea)) clientAre.WaitOne();
            //                if (clientSaea.SocketError != SocketError.Success) throw new SocketException((int)clientSaea.SocketError);

            //                if (server.ReceiveAsync(serverSaea)) serverAre.WaitOne();
            //                if (serverSaea.SocketError != SocketError.Success) throw new SocketException((int)clientSaea.SocketError);
            //            }

            //            Console.WriteLine($"Elapsed={sw.Elapsed} Gen0={GC.CollectionCount(0) - gen0} Gen1={GC.CollectionCount(1) - gen1} Gen2={GC.CollectionCount(2) - gen2}");
            //        }
            //    }
            //}


            while (true)
            {
                int remaining = 20_000_000;
                var mres = new ManualResetEventSlim();
                WaitCallback wc = null;
                wc = delegate
                {
                    if (Interlocked.Decrement(ref remaining) <= 0) mres.Set();
                    else ThreadPool.QueueUserWorkItem(wc);
                };

                var sw = new Stopwatch();
                int gen0 = GC.CollectionCount(0), gen1 = GC.CollectionCount(1), gen2 = GC.CollectionCount(2);
                sw.Start();

                for (int i = 0; i < Environment.ProcessorCount; i++) ThreadPool.QueueUserWorkItem(wc);
                mres.Wait();

                Console.WriteLine($"Elapsed={sw.Elapsed} Gen0={GC.CollectionCount(0) - gen0} Gen1={GC.CollectionCount(1) - gen1} Gen2={GC.CollectionCount(2) - gen2}");
            }



            Console.ReadLine();
        }
    }
}
